package com.xingshang.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xingshang.constant.FileLocationConstant;
import com.xingshang.model.dto.GoodsDto;
import com.xingshang.model.po.GoodDoc;
import com.xingshang.model.po.Goods;
import com.xingshang.model.vo.SearchVo;
import com.xingshang.service.GoodsService;
import com.xingshang.mapper.GoodsMapper;
import com.xingshang.util.FileStorageUtilFactory;
import com.xingshang.util.MinioUtil;
import com.xingshang.util.RedisService;
import lombok.RequiredArgsConstructor;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;


/**
 * @author 87547
 * @description 针对表【wn_goods】的数据库操作Service实现
 * @createDate 2025-03-31 16:48:21
 */
@Service
@RequiredArgsConstructor
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods>
        implements GoodsService {

    private final GoodsMapper goodsMapper;
    private final RedisService redisService;
    private final FileStorageUtilFactory fileStorageUtilFactory;
    private final MinioUtil minioUtil;
    private final RestHighLevelClient client;


    @Override
    public List<Goods> selectNewAll() {

        return lambdaQuery().eq(Goods::getNewest, "Y").eq(Goods::getStatus, "Y").list();
    }

    @Override
    public List<Goods> selectHotAll() {
        List<Goods> cachedData = (List<Goods>) redisService.getHotGoods();
        if (cachedData != null) {
            System.out.println("使用缓存查询热门商品");
            return cachedData;
        }
        List<Goods> list = lambdaQuery().eq(Goods::getHottest, "Y").eq(Goods::getStatus, "Y").list();
        redisService.cacheHotGoods(list);
        return list;
    }

    @Override
    public IPage<Goods> findByPage(int page, int pageSize) {
        IPage<?> cachedData = redisService.getGoodsPage(page);
        if (cachedData != null) {
            System.out.println("使用缓存：第" + page + "页数据");
//            System.out.println(cachedData);
            return (IPage<Goods>) cachedData;
        }
        IPage<Goods> goodsIPage = new Page<>(page, pageSize);
        QueryWrapper<Goods> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("newest", "Y");
        queryWrapper.eq("status", "Y");
        IPage<Goods> goodsIPage1 = goodsMapper.selectPage(goodsIPage, queryWrapper);

        // 将数据存入缓存
        redisService.cacheGoodsPage(page, goodsIPage1);
        return goodsIPage1;
    }

    @Override
    public boolean insertGood(GoodsDto goodsDto) {
        Goods goods = new Goods();
        BeanUtil.copyProperties(goodsDto, goods);
        System.out.println(goods);
        goods.setStatus("Y");
        goods.setSaleTime(new Date());
        boolean save = save(goods);
        if (save) {
            //往es存一份
            GoodDoc goodDoc = new GoodDoc();
            BeanUtil.copyProperties(goods, goodDoc);
            try {
                addGoodDoc(goodDoc);
            } catch (Exception e) {
                log.error("添加商品文档失败：{}", e);
            }
        }
        return save;
    }

    public void addGoodDoc(GoodDoc goodDoc) throws Exception {
        IndexRequest request = new IndexRequest("wn_goods").id(goodDoc.getId());
        request.source(JSONUtil.toJsonStr(goodDoc), XContentType.JSON);
        client.index(request, RequestOptions.DEFAULT);
    }


    @Override
    public String addMediaFilesToMinIO(MultipartFile file) throws Exception {
        String originalFilename = file.getOriginalFilename();
        String fileName = minioUtil.generateFileName(originalFilename);
        // 执行上传
        // 返回文件URL
        return fileStorageUtilFactory.getStorageUtil().uploadFile(file, fileName, FileLocationConstant.GOODS_PHOTOS_PATH);
    }


    @Override
    public SearchVo<GoodDoc> search(Integer categoryId, String searchName, int page, int pageSize) throws IOException {
        SearchRequest request = new SearchRequest("wn_goods");
        if (searchName == null || searchName.isEmpty()) {
            if (categoryId != null && categoryId != 0) {
                System.out.println("搜索类别"+categoryId);
                request.source().query(
                        QueryBuilders.boolQuery()
                                .filter(QueryBuilders.termQuery("newest", "Y"))
                                .filter(QueryBuilders.termQuery("categoryId", categoryId.toString()))
                );
            } else {
                //搜索全部
                request.source().query(
                        QueryBuilders.boolQuery()
                                .filter(QueryBuilders.termQuery("newest", "Y"))
                );
            }
        } else {
            request.source().query(
                    QueryBuilders.boolQuery()
                            .must(QueryBuilders.multiMatchQuery(searchName, "name", "no", "description"))
                            .filter(QueryBuilders.termQuery("newest", "Y"))
            );
            request.source().highlighter(SearchSourceBuilder.highlight().field("name"));
        }


        request.source().from((page - 1) * pageSize).size(pageSize);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        return parseResponseResult(response);
    }

    private static SearchVo<GoodDoc> parseResponseResult(SearchResponse response) {
        SearchHits hits = response.getHits();
        //总条数
        long total = hits.getTotalHits().value;
        System.out.println("总记录数：" + total);
        //命中的数据
        SearchHit[] searchHits = hits.getHits();
        List<GoodDoc> list = new ArrayList<>();
        for (SearchHit hit : searchHits) {
            String json = hit.getSourceAsString();
            GoodDoc gooddoc = JSONUtil.toBean(json, GoodDoc.class);
            Map<String, HighlightField> hfs = hit.getHighlightFields();
            if (CollectionUtils.isNotEmpty(hfs)) {
                HighlightField hf = hfs.get("name");
                if (hf != null) {
                    String hfName = hf.getFragments()[0].string();
                    gooddoc.setName(hfName);
                }
            }
            list.add(gooddoc);
        }
        return SearchVo.<GoodDoc>builder()
                .total(total)
                .list(list)
                .build();
    }


}




